﻿using FMStudio.Documents.TemplateDocument.Properties;
using System;
using System.IO;
using System.Xml.Serialization;
using BigEgg.Framework.Foundation;
using System.Xml.Linq;
using System.ComponentModel.Composition;

namespace FMStudio.Documents.TemplateDocument
{
    [Export(typeof(IDocumentType)), Export]
    public class TemplateDocumentType : DocumentType<TemplateDocument>
    {
        public TemplateDocumentType()
            : base(Resources.DocumentDescription, Resources.DocumentExtension)
        {
        }


        #region Methods
        #region Public Methods
        public override bool CanNew() { return true; }

        public override bool CanOpen() { return true; }

        /// <summary>
        /// create a new document with a specified file path.
        /// </summary>
        /// <param name="filePath">The file path to create the document.</param>
        /// <returns>The document.</returns>
        public TemplateDocument New(string filePath, TemplateType type)
        {
            if (string.IsNullOrEmpty(filePath)) { throw new ArgumentException("filePath must not be null or empty."); }
            if (filePath.Substring(filePath.Length - FileExtension.Length).CompareTo(FileExtension) != 0)
                filePath = filePath + FileExtension;
            if (!Path.IsPathRooted(filePath)) { throw new ArgumentException("filePath"); }
            if (!CanNew()) { throw new NotSupportedException("The New operation is not supported. CanNew returned false."); }

            if (File.Exists(filePath)) { throw new ArgumentException("The file has already exist."); };

            TemplateDocument document = NewCore(filePath, type);
            if (document != null)
            {
                document.FilePath = filePath;
                document.IsModified = true;
            }
            return document;
        }
        #endregion

        #region Protected Methods
        protected override TemplateDocument NewCore(string filePath)
        {
            return NewCore(filePath, TemplateType.Project);
        }

        protected TemplateDocument NewCore(string filePath, TemplateType type)
        {
            TemplateDocument document;

            document = new TemplateDocument(type);

            document.TemplateData.Name = Path.GetFileNameWithoutExtension(filePath);
            if (type == TemplateType.Project)
                document.TemplateData.DefaultName = "Project";
            else
                document.TemplateData.DefaultName = "Item";

            return document;
        }

        protected override TemplateDocument OpenCore(string filePath)
        {
            if (string.IsNullOrEmpty(filePath)) { throw new ArgumentException("filePath"); }
            if (!File.Exists(filePath)) { throw new FileNotFoundException("filePath"); }

            XmlSerializer serializer;

            serializer = new XmlSerializer(typeof(TemplateDocument));
            using (StreamReader sr = new StreamReader(filePath))
            {
                return serializer.Deserialize(sr) as TemplateDocument;
            }
        }

        protected override bool CanSaveCore() { return true; }

        protected override void SaveCore(TemplateDocument document, string filePath)
        {
            if (string.IsNullOrWhiteSpace(filePath)) { throw new NotSupportedException("filePath"); }

            if (!CanSave(document))
            {
                throw new InvalidOperationException("You must not call Save when CanSave returns false.");
            }

            XmlSerializerNamespaces xns = new XmlSerializerNamespaces();
            xns.Add(string.Empty, string.Empty);
            XmlSerializer serializer;

            serializer = new XmlSerializer(typeof(TemplateDocument));

            using (StreamWriter sw = new StreamWriter(filePath, false))
            {
                serializer.Serialize(sw, document, xns);

                sw.Close();
            }
        }
        #endregion
        #endregion
    }
}